﻿using SignalBox.Core.Util;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;

namespace SignalBox.Core.Model.Graph
{
    public class GraphNode
    {
        private TrackCell trackCell;
        private Dictionary<DIRECTION, GraphNode> connections;
        private List<DIRECTION> mustHaveConnections;

        public GraphNode(TrackCell cell)
        {
            trackCell = cell;
            connections = new Dictionary<DIRECTION, GraphNode>();
            mustHaveConnections = new List<DIRECTION>();

            init();
        }

        public TrackCell Cell
        {
            get { return trackCell; }
        }

        public Point getCellCoordinates()
        {
            var p = new Point(trackCell.X, trackCell.Y);
            return p;
        }

        public void addConnection(DIRECTION dir, GraphNode other)
        {
            connections[dir] = other;
        }


        public GraphNode GetNextNode(DIRECTION dir)
        {
            if (connections.ContainsKey(dir))
                return connections[dir];
            return null;
        }

        

        public DIRECTION GetNextDirectionFromInput(DIRECTION dir)
        {


            if (trackCell.TrackCellType.Category == "ENTRYEXIT")
            {
                
            }

            Dictionary<DIRECTION, DIRECTION> routes = trackCell.TrackCellType.GetRoutes(trackCell.State);

            if (routes.ContainsKey(dir))
            {

                trackCell.RouteFindingState = trackCell.State;

                DIRECTION outputDir = routes[dir];
                return outputDir;

            }

            if (trackCell.TrackCellType.Category == "CROSS")
            {
                int state = trackCell.State;
                state++;

                if (state == 3) state = 1;

                routes = trackCell.TrackCellType.GetRoutes(state);

                if (routes.ContainsKey(dir))
                {
                    trackCell.RouteFindingState = state;
                    DIRECTION outputDir = routes[dir];
                    return outputDir;

                }
            }

            return DIRECTION.INVALID;

        }

        public void cleanConnections()
        {
            if (trackCell.TrackCellType.Category == "SWITCH")
            {
                Dictionary<DIRECTION, DIRECTION> routes = trackCell.TrackCellType.GetRoutes(trackCell.State);

                List<DIRECTION> toRemove = new List<DIRECTION>();

                foreach (DIRECTION dir in connections.Keys)
                {
                    if (!routes.ContainsKey(dir))
                    {
                        toRemove.Add(dir);
                    }
                }

                foreach (DIRECTION dir in toRemove)
                {
                    connections.Remove(dir);
                }

            }

        }

        private void init()
        {
            var tct = TrackCellType.TrackCellTypes[trackCell.Type];

            if (tct.HasE)
            {
                mustHaveConnections.Add(DIRECTION.E);
            }
            if (tct.HasN)
            {
                mustHaveConnections.Add(DIRECTION.N);
            }
            if (tct.HasW)
            {
                mustHaveConnections.Add(DIRECTION.W);
            }
            if (tct.HasS)
            {
                mustHaveConnections.Add(DIRECTION.S);
            }
            if (tct.HasNE)
            {
                mustHaveConnections.Add(DIRECTION.NE);
            }
            if (tct.HasSE)
            {
                mustHaveConnections.Add(DIRECTION.SE);
            }
            if (tct.HasSW)
            {
                mustHaveConnections.Add(DIRECTION.SW);
            }
            if (tct.HasNW)
            {
                mustHaveConnections.Add(DIRECTION.NW);
            }
        }

        public bool isValid()
        {
            foreach (DIRECTION dir in mustHaveConnections)
            {
                if (!connections.ContainsKey(dir))
                {
                    return false;
                }
            }

            return true;
        }
    }
}
